﻿using System;
using System.Windows.Forms;
using System.Threading;
using NLog;
using UtfprLibrary.Extensions;

namespace UtfprLibrary.Windows.Forms {
    /// <summary>
    /// TODO
    /// </summary>
    public class UtfprApplicationContext : ApplicationContext {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        #region Singleton

        /// <summary>
        /// TODO
        /// </summary>
        private UtfprApplicationContext() {
            if (UtfprApplication.Instance.IsLoginEnabled) {
                base.MainForm = UtfprApplication.Instance.FormLoginDefault;
            } else {
                base.MainForm = UtfprApplication.Instance.FormMainDefault;
                //base.MainForm.WindowState = FormWindowState.Minimized;
                //base.MainForm.ShowInTaskbar = false;
            }
        }

        private static UtfprApplicationContext _utfprApplicationContext;

        /// <summary>
        /// TODO
        /// </summary>
        public static UtfprApplicationContext Instance {
            get {                
                if (_utfprApplicationContext == null) {
                    // Add the event handler for handling UI thread exceptions to the event.
                    Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(application_ThreadException);

                    // Add the event handler for handling non-UI thread exceptions to the event. 
                    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);

                    _utfprApplicationContext = new UtfprApplicationContext();
                }

                return _utfprApplicationContext;
            }
        }

        #endregion

        #region Exception Handlers

        private static void application_ThreadException(object sender, ThreadExceptionEventArgs e) {
            UtfprApplicationContext.Instance.OnThreadException(e);
        }

        private static void currentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            UtfprApplicationContext.Instance.OnUnhandledException(e);
        }

        #endregion

        #region Events

        public event UnhandledExceptionEventHandler UnhandledException;

        protected virtual void OnUnhandledException(UnhandledExceptionEventArgs e) {
            if (UnhandledException == null) {
                handleException((Exception)e.ExceptionObject);
            } else {
                UnhandledException(this, e);
            }
        }

        public event ThreadExceptionEventHandler ThreadException;

        protected virtual void OnThreadException(ThreadExceptionEventArgs e) {
            if (ThreadException == null) {
                handleException(e.Exception);
            } else {
                ThreadException(this, e);
            }
        }

        #endregion

        #region Methods

        private static void handleException(Exception ex) {
            if (UtfprApplication.Instance._isInDebugMode) {
                MessageBox.Show(ex.GetAllExceptionMessages(), "All Exception Messages", MessageBoxButtons.OK, MessageBoxIcon.Error);
                MessageBox.Show(ex.StackTrace, "Exception StackTrace", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } else {
                MessageBox.Show("A aplicação disparou uma exceção e precisa ser fechada :(", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                var theEvent = new LogEventInfo(LogLevel.Info, "dbLog", ex.Message);
                theEvent.Exception = ex;
                theEvent.Properties.Add("Source", ex.Source);
                logger.Log(theEvent);
                Application.Exit();
            }
        }

        #endregion
    }
}
